package com.unicom.office.node;

import com.unicom.office.func.FuncBase;
import com.unicom.office.func.FuncCommon;
import com.unicom.office.func.ProcNode;
import com.unicom.office.runtime.OfficeRuntime;
import com.unicom.office.unit.OfficeUnit;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;


public abstract class OfficeNode extends FuncBase{
    private Object source;
    private FuncBase parent;
    private List<FuncBase> children;
    private List<ProcNode> procs;

    public OfficeNode(Object source){
        this.source = source;
        children = new ArrayList<FuncBase>();
        procs = new ArrayList<ProcNode>();
    }

    public Object getSource(){
        return this.source;
    }

    public void setSource(Object source){
        this.source = source;
    }

    public void addChild(FuncCommon child){
        if(!testChildType(child)){
            throw new RuntimeException("子节点类型不匹配");
        }
        if(child instanceof OfficeNode){
            ((OfficeNode)child).setParent(this);
        }
        if(child instanceof FuncBase){
            children.add((FuncBase)child);
        }else{
            procs.add((ProcNode)child);
        }
    }

    public void addProc(ProcNode proc){
        procs.add(proc);
    }

    public List<FuncBase> getChildren(){
        return this.children;
    }

    public abstract OfficeUnit createUnit();

    public abstract boolean testChildType(FuncCommon child);

    public Object run(OfficeRuntime officeRuntime) {
        OfficeUnit unit = createUnit();
        unit.setSource(source);
        unit.setJustResource(justResource());
        for (ProcNode proc : procs) {
            proc.run(unit, officeRuntime);
        }
        for (FuncBase func : children) {
            Object obj = func.run(officeRuntime);
            if(obj instanceof OfficeUnit){
                // 例如textbox的话，addChild就会将child添加到textboxes中
                unit.addChild((OfficeUnit) obj);
            }else if(obj instanceof List){
                unit.addChildren((List<OfficeUnit>)obj);
            }else {
                throw new RuntimeException("返回值类型不正确");
            }
        }
        return unit;
    }

    public FuncBase getParent() {
        return parent;
    }

    public void setParent(FuncBase parent) {
        this.parent = parent;
    }

    public List<ProcNode> getProcs() {
        return procs;
    }

    public void runForMatch(OfficeUnit unit, OfficeRuntime officeRuntime) {
        Iterator<OfficeUnit> iterator = unit.getChildren().iterator();
        for (FuncBase child : children) {
            while (true){
                if(!iterator.hasNext()) {
                    //throw new RuntimeException("节点与节点不匹配");
                    break;
                }
                OfficeUnit next = iterator.next();
                if(!next.isMatched()){
                    child.runForMatch(next, officeRuntime);
                    break;
                }
            }
        }
        // 给unit加matched标签
        unit.setMatched(true);
    }

    public boolean justResource(){
        if(procs.size() > 0) {
            return false;
        }
        for (FuncBase child : children) {
            if(child instanceof OfficeNode){
                if(!((OfficeNode) child).justResource()){
                    return false;
                }
            }else {
                return false;
            }
        }
        return true;
    }
}
